#include "thread_pool.h"
#include "linked_list.h"
#include "sql_util.h"

#define EPOLL_ARR_SIZE 100
#define CONFIG_NAME "../conf/server.conf"

// wmx-用于存储用户的信息，user_list就是这个链表的头指针
ListNode *user_list = NULL;
// 全局的mysql连接
MYSQL *mysql;
int exitPipe[2];

void sigHandler(int num)
{
    printf("\n sig is coming.\n");
    //激活管道, 往管道中写一个1
    int one = 1;
    write(exitPipe[1], &one, sizeof(one));
}

int main(int argc, char ** argv)
{   //ip,port,threadNum
    char str_ip[256];
    char str_port[256];
    char str_num[25];
    char filename[256]=CONFIG_NAME;
   
    int ret=GetIniKeyString("server","ip",filename,str_ip);
    WriteLog("get ret:%d, str_ip: %s", ret, str_ip);
    
    ret= GetIniKeyString("server","port",filename,str_port);
    WriteLog("get ret:%d, str_port: %s", ret, str_port);

    ret= GetIniKeyString("server","thread_num",filename,str_num);
    WriteLog("get ret:%d, str_num: %s", ret, str_num);

    WriteLog("sizeof(CmdType):%lu", sizeof(CmdType));
    
    //创建匿名管道
    pipe(exitPipe);

    //fork之后，将创建了子进程
    pid_t pid = fork();
    if(pid > 0) {//父进程
        close(exitPipe[0]);//父进程关闭读端
        signal(SIGUSR1, sigHandler);
        wait(NULL);//等待子进程退出，回收其资源
        close(exitPipe[1]);
        WriteLog("\nparent process exit.");
        exit(0);//父进程退出
    }
    //子进程
    close(exitPipe[1]);//子进程关闭写端

    threadpool_t threadpool;
    memset(&threadpool, 0, sizeof(threadpool));

    //初始化线程池
    threadpoolInit(&threadpool, atoi(str_num));
    //启动线程池
    threadpoolStart(&threadpool);

    //创建监听套接字
    int listenfd = tcpInit(str_ip, str_port);

    //创建epoll实例
    int epfd = epoll_create1(0);
    ERROR_CHECK(epfd, -1, "epoll_create1");

    //对listenfd进行监听
    addEpollReadfd(epfd, listenfd);
    addEpollReadfd(epfd, exitPipe[0]);

    struct epoll_event * pEventArr = (struct epoll_event*)
        calloc(EPOLL_ARR_SIZE, sizeof(struct epoll_event));

    /* -------------------- 连接MySQL数据库 ----------------------- */
    //与MySQL服务器建立连接
    //下面这段代码放出来就能从配置文件读数据库信息,不用写死在代码里面
    /* 在配置文件加上这个就行
        [mysql]
        ip=127.0.0.1
        user=root
        passwd=1234
    */
    /*
    char MYSQLIP[256];
    char MYSQLUSERNAME[256];
    char MYSQLPASSWD[256]; 
    ret= GetIniKeyString("mysql","ip",filename,MYSQLIP);
    WriteLog("get ret:%d, MYSQLIP: %s", ret, MYSQLIP);
    ret= GetIniKeyString("mysql","user",filename,MYSQLUSERNAME);
    WriteLog("get ret:%d, MYSQLUSERNAME: %s", ret, MYSQLUSERNAME);
    ret= GetIniKeyString("mysql","passwd",filename,MYSQLPASSWD);
    //WriteLog("get ret:%d, MYSQLPASSWD: %s", ret, MYSQLPASSWD);
    MYSQL* mysql = mysql_connect("MYSQLIP", "MYSQLUSERNAME", "MYSQLPASSWD", "cloudservice"); 

    */


    mysql = mysql_connect("localhost", "root", "1234", "cloudservice"); 

   
    while(1) {
        int nready = epoll_wait(epfd, pEventArr, EPOLL_ARR_SIZE, -1);
        if(nready == -1 && errno == EINTR) {
            continue;
        } else if(nready == -1) {
            ERROR_CHECK(nready, -1, "epoll_wait");
        } else {
            //大于0
            for(int i = 0; i < nready; ++i) {
                int fd = pEventArr[i].data.fd;
                if(fd == listenfd) {
                    //对新连接进行处理
                    int peerfd = accept(listenfd, NULL, NULL);
                    printf("\n conn %d has conneted.\n", peerfd);
                    //将新连接添加到epoll的监听红黑树上
                    addEpollReadfd(epfd, peerfd);

                    // 将新用户，添加到用户链表中
                    user_info_t *user = (user_info_t *) calloc(1, sizeof(user_info_t));
                    user->net_fd = peerfd;
                    appendNode(&user_list, user);
                } else if(fd == exitPipe[0]) {
                    //线程池要退出
                    int howmany = 0;
                    //对管道进行处理
                    read(exitPipe[0], &howmany, sizeof(howmany));
                    //主线程通知所有的子线程退出
                    threadpoolStop(&threadpool);
                    //子进程退出前，回收资源
                    threadpoolDestroy(&threadpool);
                    close(listenfd);
                    close(epfd);
                    close(exitPipe[0]);
                    printf("\nchild process exit.\n");
                    exit(0);
                } else {
                    //客户端的连接的处理
                    handleMessage(fd, epfd, &threadpool.que);
                }
            }
        }
    }

    return 0;
}


